<?php
/*
 * Class teia\webdev\php\core\Product
* Core class for electronic shopping product
*
* @author Bernardo Quibiana
* @date created: 20111011
*
* @date modified: 20111023
* @modified: Bernardo Quibiana
*/

// namespace declaration: Abstract Data Types
namespace teia\webdev\php\core;

require_once 'DisplayableItem.inc';
require_once 'FunctionPool.inc';

class Product extends DisplayableItem {

	/*
	 * Product properties
	*/
	protected $prod_id;
	protected $prod_name;
	protected $prod_type;
	protected $prod_descr;
	protected $prod_gender;
	protected $prod_price;

	/*
	 * Product itemization
	*/
	protected $item_array;
	protected $feat_item;
	protected $active_item;

	/*
	 * Constants
	*/

	const DEFAULT_LIMIT = 120;
	const MIN_NUM_ITEMS = 1;
	
	/*
	 * Production
	*/

	/**
	 * Initializes a Product object
	 * @param string $id product id
	 * @param string $name product name
	 * @param array $var_array associative array of product properties
	 */
	public function __construct($id, $name, $var_array=NULL) {
		parent::__construct($id, $name, $var_array);
		$this->active_item = null;
	}

	/**
	 * Generates an array of Product objects using data fetched from the database
	 * @param array $fields relevant product properties to fetch
	 * @param array $conds condition for fetching products
	 * @param int $limit expected number of products to be fetched
	 * @param string $db_tb name of the database table with products
	 * @return array associate array of Product objects (key: product id, value: product object) fetched from the database
	 */
	static function db_factory($fields=NULL, $conds=NULL, $limit=0, $db_tb ='ecom_prod') {
		$prods = array();
		
		if ($limit < 1)	$limit = self::DEFAULT_LIMIT;
		if (is_null($fields))	$fields = self::default_fields();
		$prod_filter = isset($conds['prod_filter']) ? $conds['prod_filter'] : null;
		$item_filter = isset($conds['item_filter']) ? $conds['item_filter'] : array();
		// execute query
		$db_link = MySqlLink::link_factory();
		$result = $db_link->select($db_tb, $fields, $prod_filter, $limit);
		if ($result && is_resource($result)) {
			// fetch product
			while ($result_row = mysql_fetch_assoc($result)) {
				// synthesize product object
				$prod = self::db_synthesis($result_row, null, $item_filter);
				// add product object to array using its id as key
				$prod_id = $prod->get_prod_id();
				if ($prod->get_num_items() >= self::MIN_NUM_ITEMS) {
					$prods[$prod_id] = $prod;
				} else {
					//throw new \Exception("Product: Insufficient number of items", 100);
				}
				//echo "Loaded product '$prod_id'<br />\n";
			}
		} else {
			throw new \Exception("Product: Unable to fetch products from database", 100);
		}
		return $prods;
	}

	/**
	 * Fetch a Product object from the database
	 * @param string $prod_id product id
	 * @param array $fields relevant product properties to fetch
	 * @param string $db_tb_prod name of the database table with products
	 * @param string $db_tb_prod_it name of the database table with product-items
	 * @throws \Exception
	 * @return Product returns a Product object
	 */
	static function db_fetch($prod_id, $fields=NULL, $item_filter=NULL, $db_tb ='ecom_prod') {
		$prod = null;
		$limit = 1;
		$prod_filter = array('prod_id' => $prod_id);
		if (is_null($fields))	$fields = self::default_fields();
		// execute query
		$db_link = MySqlLink::link_factory();
		$result = $db_link->select($db_tb, $fields, $prod_filter, $limit);
		if ($result && is_resource($result)) {
			// read product fields
			$result_row = mysql_fetch_assoc($result);
			// synthesize product object
			$prod = self::db_synthesis($result_row, null, $item_filter);
		} else {
			throw new \Exception("Product: Unable to fetch product '$prod_id' from database", 100);
		}

		return $prod;
	}

	/**
	 * Enter description here ...
	 * @param array $tb_row
	 * @return \teia\webdev\php\core\Product
	 */
	static function db_synthesis($tb_row, $item_fields=NULL, $item_filter=NULL, $item_limit=0,  $db_tb_prod_it='ecom_prod_item') {
		$prod = new Product('', '', $tb_row);
		$prod->db_fetch_items($item_fields, $item_filter, $item_limit,  $db_tb_prod_it);

		return $prod;
	}

	protected function db_fetch_items($fields=NULL, $conds=NULL, $limit=0, $db_tb_prod_it='ecom_prod_item') {
		$this->item_array = ProductItem::db_factory($this, $fields, $conds, $limit, $db_tb_prod_it);
	}

	static function default_fields() {
		return array('prod_id', 'prod_name', 'prod_type', 'prod_subtype', 'prod_brand', 'prod_gender', 'prod_descr', 'prod_price', 'prod_events');
	}
	
	/*
	 * Instance methods
	*/

	public function get_prod_id() {
		return $this->prod_id;
	}

	public function get_prod_price() {
		return $this->prod_price;
	}

	public function get_prod_name() {
		return $this->prod_name;;
	}

	public function get($property) {
		return isset($this->$property) ? $this->$property : null;	
	}
	
	public function get_item_obj($item_id) {
		return isset($this->item_array[$item_id]) ? $this->item_array[$item_id] : null;
	}
	
	public function set_active_item($item_id) {
		if (isset($this->item_array[$item_id])) {
			$this->active_item = $this->item_array[$item_id];
			return true;
		}
		return false;
	}		
	
	public function activate_item($field, $value) {
		foreach ($this->item_array as $it_obj) {
			$it_value = $it_obj->get($field);
			if (!is_null($it_value) && $it_value == $value) {
				$this->active_item = $it_obj;
				return $it_obj;
			}
		}
		return false;
	}
	
	public function get_active_item() {
		if ($this->active_item) {
			// use the currently active item
			return $this->active_item;
		} elseif ($this->feat_item) {
			// use the featured item
			return $this->feat_item;
		} else {
			// return an element from the array
			return FunctionPool::array_peek($this->item_array);
		}
		return  $this->active_item;
	}
	
	public function find_item($field, $value) {
		foreach ($this->item_array as $it_obj) {
			$it_value = $it_obj->get($field);
			if (!is_null($it_value) && $it_value == $value) {
				return $it_obj;
			}
		}
		return null;
	}
	
	public function get_num_items(){
		return count($this->item_array);
	}
	
	/**
	 * Check whether the product has a given item
	 * @param string $item_id item id to be checked
	 * @return boolean return true if the item is contained in the product, otherwise false
	 */
	public function has_item($item_id) {
		return array_key_exists($item_id, $this->item_array);
	}

	public function get_all_values($item_field) {
		$all_values = array();
		foreach ($this->item_array as $item) {
			$value = $item->get($item_field);
			array_push($all_values, $value);
		}
		return $all_values;
	}
	
	public function get_all_colors() {
		return $this->get_all_values('item_color');
	}
	
	public function get_all_sizes() {
		return $this->get_all_values('item_size');
	}
	
	public function get_link() {
		if ($this->link) {
			return $this->link;
		} else {
			return "ProductPage.php?Product_id=$this->id";
		}
	}

	/*
	 * Display
	*/

	public function generate_thumbnail() {
		$this->active_item = $this->get_active_item();
		$it_id = $this->active_item->get_item_id();
		//echo "Product: $this->prod_id - $it_id<br />\n";
		return $this->active_item->generate_thumbnail();
	}
	
	public function generate_all_thumbnails($skip_active) {
		$content = '';
		$active_id = $skip_active ? $this->active_item->get_item_id() : null;
		foreach ($this->item_array as $item_id => $item_obj) {
			if ($active_id != $item_id) {
				//echo "Item: $item_id<br />";
				$content .= $item_obj->generate_thumbnail() . "\n";
			}
		}
		return $content;
	}

	public function generate_slide() {
		$this->active_item = $this->get_active_item();
		
		return $this->active_item->generate_slide();
	}

	public function generate_medium_img() {
		$this->active_item = $this->get_active_item();
		return $this->active_item->generate_medium_img();
	}
	
	public function generate_page() {
		$code = "<div class=\"product_page\">
					<div class=\"active_item_img\">
					</div>
					<div class=\"left_pane\">
						<div class=\"attrib_pane\">
							<div class=\"prod_attrib\">
							</div>
							<div class=\"item_attrib\">
							</div>
						</div>
					</div>";

		return $code;
	}
}

?>